<template>
  <el-form :model="formData" label-width="0" class="desc-music-form" ref="descFormRef">
    <Title title="音乐名称" required>
      <el-form-item
        class="!mb-0"
        prop="title"
        :rules="[{ required: true, message: '请输入音乐名称', trigger: 'blur' }]"
      >
        <el-input
          class="music-ai-input"
          v-model="formData.title"
          placeholder="请输入音乐/歌曲名称"
          maxlength="30"
        />
      </el-form-item>
    </Title>
    <Title v-if="type === 'lyric'" title="歌词" required>
      <el-form-item
        class="!mb-0"
        prop="lyrics"
        :rules="[{ validator: lyricsValidator, trigger: 'blur' }]"
      >
        <el-input
          class="music-ai-input"
          v-model="formData.lyrics"
          :rows="4"
          type="textarea"
          maxlength="2000"
          show-word-limit
          placeholder="请输入您自己的歌词"
        />
      </el-form-item>
    </Title>

    <Title
      :title="type === 'lyric' ? '提示词' : '描述'"
      :desc="
        type === 'lyric'
          ? '可选，若未填写歌词可用提示词生成歌曲'
          : '建议描述风格、氛围、乐器等，丰富内容更易生成优质音乐'
      "
      :required="type !== 'lyric'"
    >
      <el-form-item
        class="!mb-0"
        prop="prompt"
        :rules="[{ required: type !== 'lyric', validator: promptValidator, trigger: 'blur' }]"
      >
        <el-input
          class="music-ai-input"
          v-model="formData.prompt"
          :rows="4"
          type="textarea"
          maxlength="500"
          show-word-limit
          placeholder="请输入歌词提示词，仅支持中文"
        />
      </el-form-item>
    </Title>

    <Title title="曲风">
      <el-select
        class="music-ai-input"
        v-model="formData.genreSong"
        placeholder="请选择曲风"
        style="width: 100%"
      >
        <el-option
          v-for="item in genreOptions"
          :key="item.value"
          :label="item.label"
          :value="item.value"
        />
      </el-select>
    </Title>

    <Title title="风格">
      <el-select
        class="music-ai-input"
        v-model="formData.moodSong"
        placeholder="请选择风格"
        style="width: 100%"
      >
        <el-option
          v-for="item in moodOptions"
          :key="item.value"
          :label="item.label"
          :value="item.value"
        />
      </el-select>
    </Title>

    <Title title="性别">
      <el-select
        class="music-ai-input"
        v-model="formData.gender"
        placeholder="请选择性别"
        style="width: 100%"
      >
        <el-option
          v-for="item in genderOptions"
          :key="item.value"
          :label="item.label"
          :value="item.value"
        />
      </el-select>
    </Title>

    <Title title="音色">
      <el-select
        class="music-ai-input"
        v-model="formData.timbre"
        placeholder="请选择音色"
        style="width: 100%"
      >
        <el-option
          v-for="item in timbreOptions"
          :key="item.value"
          :label="item.label"
          :value="item.value"
        />
      </el-select>
    </Title>

    <Title title="时长" desc="生成指定音频时长，生效范围[30，240]">
      <el-input-number v-model="formData.duration" :min="30" :max="240" />
      <span class="ml-2">秒</span>
    </Title>
  </el-form>
</template>

<script lang="ts" setup>
import { reactive, ref, defineExpose } from 'vue'
import Title from '../title/index.vue'

defineOptions({ name: 'Lyric' })
const props = defineProps({
  type: {
    type: String,
    default: 'lyric'
  }
})
const genreOptions = [
  { value: 'Folk', label: '民谣' },
  { value: 'Pop', label: '流行' },
  { value: 'Rock', label: '摇滚' },
  { value: 'Chinese Style', label: '国风' },
  { value: 'Hip Hop/Rap', label: '嘻哈' },
  { value: 'R&B/Soul', label: 'R&B' },
  { value: 'Punk', label: '朋克' },
  { value: 'Electronic', label: '电子' },
  { value: 'Jazz', label: '爵士' },
  { value: 'Reggae', label: '雷鬼' },
  { value: 'DJ', label: 'DJ' },
  { value: 'Pop Punk', label: '流行朋克' },
  { value: 'Disco', label: '迪斯科舞曲' },
  { value: 'Future Bass', label: '未来贝斯' },
  { value: 'Pop Rap', label: '流行说唱' },
  { value: 'Trap Rap', label: '陷阱说唱' },
  { value: 'R&B Rap', label: '旋律说唱' },
  { value: 'Chinoiserie Electronic', label: '国风电子' },
  { value: 'GuFeng Music', label: '古风音乐' },
  { value: 'Pop Rock', label: '流行摇滚' },
  { value: 'Jazz Pop', label: '流行爵士' },
  { value: 'Bossa Nova', label: '巴塞诺瓦' },
  { value: 'Contemporary R&B', label: '当代节奏布鲁斯' }
]
const moodOptions = [
  { value: 'Happy', label: '快乐' },
  { value: 'Dynamic/Energetic', label: '活力' },
  { value: 'Sentimental/Melancholic/Lonely', label: 'EMO' },
  { value: 'Inspirational/Hopeful', label: '鼓舞' },
  { value: 'Nostalgic/Memory', label: '怀旧' },
  { value: 'Excited', label: '兴奋' },
  { value: 'Sorrow/Sad', label: '伤感' },
  { value: 'Chill', label: '放松' },
  { value: 'Romantic', label: '浪漫' },
  { value: 'Miss', label: '思念' },
  { value: 'Groovy/Funky', label: '律动' },
  { value: 'Dreamy/Ethereal', label: '梦幻' },
  { value: 'Calm/Relaxing', label: '平静' }
]
const genderOptions = [
  { value: 'Female', label: '女声' },
  { value: 'Male', label: '男声' }
]
const timbreOptions = [
  { value: 'Warm', label: '温暖' },
  { value: 'Bright', label: '明亮' },
  { value: 'Husky', label: '烟嗓' },
  { value: 'Electrified voice', label: '电音' },
  { value: 'Sweet_AUDIO_TIMBRE', label: '甜美' },
  { value: 'Cute_AUDIO_TIMBRE', label: '可爱' },
  { value: 'Loud and sonorous', label: '浑厚' },
  { value: 'Powerful', label: '高亢' },
  { value: 'Sexy/Lazy', label: '慵懒' }
]

const formData = reactive({
  generateMode: 2,
  lyrics: '',
  prompt: '',
  title: '',
  genreSong: '',
  moodSong: '',
  gender: '',
  timbre: '',
  duration: 60,
  makeInstrumental: false
})
const descFormRef = ref()

function countMixedLen(str) {
  // 中文1，英文/数字/标点0.5
  let len = 0
  for (let i = 0; i < str.length; i++) {
    const code = str.charCodeAt(i)
    if (code >= 0x4e00 && code <= 0x9fa5) {
      len += 1
    } else {
      len += 0.5
    }
  }
  return len
}

function lyricsValidator(rule, value, callback) {
  const lyrics = value?.trim() || ''
  const prompt = formData.prompt?.trim() || ''
  if (!lyrics && !prompt) {
    callback(new Error('请输入歌词或提示词'))
    return
  }
  if (lyrics) {
    const len = countMixedLen(lyrics)
    // 全英文允许最大2000字符
    const isAllEn = /^[A-Za-z0-9\s\p{P}]+$/u.test(lyrics)
    if (isAllEn) {
      if (lyrics.length < 5 || lyrics.length > 2000) {
        callback(new Error('英文歌词5-2000字符'))
        return
      }
    } else {
      if (len < 5 || len > 700) {
        callback(new Error('中文、中英文混合歌词需5-700字'))
        return
      }
    }
  }
  callback()
}
const promptValidator = (rule, value, callback) => {
  const prompt = value?.trim() || ''
  if (prompt) {
    // 只允许中文和中文标点
    const isZh = /^[\u4e00-\u9fa5\s\p{P}]+$/u.test(prompt)
    const len = countMixedLen(prompt)
    if (!isZh) {
      callback(new Error('提示词仅支持中文'))
      return
    }
    if (len < 5 || len > 500) {
      callback(new Error('提示词需5-500字（中英文混合计数）'))
      return
    }
  } else if (props.type !== 'lyric') {
    callback(new Error('请输入提示词'))
  }
  callback()
}
const setFormData = (data) => {
  formData.prompt = data.prompt || ''
  formData.title = data.title || ''
}
function validate() {
  return descFormRef.value?.validate?.() ?? true
}
defineExpose({ formData, validate, setFormData })
</script>
<style lang="scss" scoped>
.desc-music-form {
  padding: 0 10px;
}

.music-ai-input {
  overflow: hidden;
  background-image: linear-gradient(to right, #fff, #fff),
    linear-gradient(90deg, #bc9eff 0%, #8b9bff 100%);
  border: 1px solid transparent;
  border-radius: 6px;
  background-clip: padding-box, border-box;
  background-origin: padding-box, border-box;

  :deep() {
    .el-input__count {
      font-size: 12px;
      color: #8a8a8a;
    }

    .el-textarea__inner {
      &::placeholder {
        font-size: 14px;
        color: #8a8a8a;
      }
    }
  }
}
</style>
